/**
 *
 */
package ibm.websphere.monitor.common;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import ibm.websphere.monitor.exception.MonitorDaoException;
import ibm.websphere.monitor.page.PageResult;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;


/**
 * <pre>
 * @Description 菜单操作的DOMAIN
 * </pre>
 *
 * @copyright www.timotai.net
 * @author 这家伙真懒
 * @date 2016-1-12
 */
@Repository
public class DaoHelper extends HibernateDaoSupport {


    @Autowired
    public void setMySessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }


    /**
     * <pre>
     *  保存方法
     * </pre>
     *
     * @param obj 实体对象
     */
    public void save(Object obj) {
        getHibernateTemplate().save(obj);
    }

    /**
     * <pre>
     * 更新方法
     * </pre>
     *
     * @param obj 实体对象
     */
    public void update(Object obj) {
        getHibernateTemplate().update(obj);
    }

    /**
     * <pre>
     * 保存或更新方法
     * </pre>
     *
     * @param obj 实体对象
     */
    public void saveOrUpdate(Object obj) {
        getHibernateTemplate().saveOrUpdate(obj);
    }

    /**
     * <pre>
     * 删除指定的对象，该对象只包含主键即可
     * </pre>
     *
     * @param obj 实体对象
     */
    public void delete(Object obj) {
        getHibernateTemplate().delete(obj);
    }

    /**
     * <pre>
     * 	根据对象ID删除该对象
     * </pre>
     *
     * @param _class
     * @param id
     */
    public void delete(Class<?> _class, Long id) {
        delete(load(_class, id));
    }

    /**
     * <pre>
     * 	根据对象ID加载该对象
     * </pre>
     * <p/>
     * get/load 区别：
     * get 是查一次数据库，如果不存在，会返回NULL
     * load 是走缓存，如果不存在，会抛出ObjectNotFondException.
     *
     * @param _class
     * @param id
     * @return
     */
    public Object load(Class<?> _class, Long id) {
        return getHibernateTemplate().load(_class, id);
    }

    /**
     * <pre>
     * 	根据对象ID加载该对象
     * </pre>
     *
     * @param _class
     * @param id
     * @return
     */
    public Object get(Class<?> _class, Long id) {
        return getHibernateTemplate().get(_class, id);
    }

    /**
     * <pre>
     * 	根据实体名查询该对象的所有信息
     * </pre>
     *
     * @param entityName
     * @return
     */
    public List<?> findAll(String entityName) {
        return getHibernateTemplate().find("from " + entityName);
    }


    /**
     * <pre>
     *  根据实体名和条件查询该对象的所有信息
     * </pre>
     *
     * @param entityName 实体名
     * @param condition  查询的条件
     * @return
     */
    public List<?> findByCondition(String entityName, String condition) {
        return getHibernateTemplate().find("from " + entityName + " " + condition);
    }


    /**
     * <pre>
     * 	根据条件查询该对象的所有信息
     * </pre>
     *
     * @param condition  查询的条件
     * @return
     */
    public List<?> findByCondition(String condition) {
        return getHibernateTemplate().find(condition);
    }

    /**
     * <pre>
     * 	根据条件查询该对象的所有信息
     * </pre>
     *
     * @param condition  查询的条件
     * @return
     */
    public List<?> findByConditionSize(String condition) {
        return this.getSession().createSQLQuery(condition).list();
    }

    /**
     * <pre>
     * 执行自定义sql时调用，需要实现Work接口。
     * </pre>
     */
    public void doWork(Work w) {
        this.getSession().doWork(w);
    }

    /**
     * <pre>
     * 使用spring提供的 hibernate 模板处理事务
     * </pre>
     *
     * @param action 事务处理回调
     */
    protected final Object execute(HibernateCallback action) {
        return this.getHibernateTemplate().execute(action);
    }


    /**
     * @param object
     * @return
     */
    public List<?> findPage(final String object) {

        HibernateCallback callback = new HibernateCallback() {
            @SuppressWarnings("unchecked")
            List list = null;

            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                // TODO Auto-generated method stub
                list = session.createQuery("from " + object).list();
                return list;
            }
        };

        return (List<?>) execute(callback);
    }

    /**
     * <pre>
     * 	根据条件查询出分页的内容
     * </pre>
     *
     * @param condition
     * @param offset
     * @param max
     * @return
     */
    public List<?> findByCondition(final String condition, final int offset, final int max) {
        HibernateCallback callback = new HibernateCallback() {
            List<?> list = null;

            @SuppressWarnings("unchecked")
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                // TODO Auto-generated method stub
                Query query = session.createQuery(condition);
                if (offset >= 0 && max >= 0) {
                    query.setFirstResult(offset);
                    query.setMaxResults(max);
                }
                list = query.list();
                if (list == null) list = new ArrayList();
                return list;
            }
        };
        return (List<?>) execute(callback);
    }


    /**
     * <pre>
     * 	根据条件查询出分页的内容
     * </pre>
     *
     * @param condition
     * @return
     */
    public int findBySqlCount(final String condition) {
        final List<Integer> flowInfoAll = new ArrayList<Integer>();
        doWork(new Work() {
            public void execute(Connection conn) {
                Statement stat = null;
                ResultSet rs = null;
                try {
                    stat = conn.createStatement();
                    rs = stat.executeQuery(condition);

                    while (rs.next()) {
                        flowInfoAll.add(rs.getInt(1));
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    if (rs != null) {
                        try {
                            rs.close();
                            stat.close();
                            conn.close();
                        } catch (Exception ex) {

                        }
                    }
                }
            }
        });
        return flowInfoAll.get(0);
    }

    /**
     * @param <T>
     * @param entity
     * @param crits
     * @param order
     * @param offset
     * @param maxResults
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> PageResult<T> findPageResult(
            final Class<T> entity, final Criterion[] crits, final Order order,
            final int offset, final int maxResults)
            throws MonitorDaoException {
        Object result = execute(new HibernateCallback() {
            @SuppressWarnings("unchecked")
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                try {
                    Criteria crit = session.createCriteria(entity);
                    Criteria countCrit = session.createCriteria(entity);

                    if (offset >= 0 && maxResults >= 0) {
                        crit.setFirstResult(offset);
                        crit.setMaxResults(maxResults);
                    }
                    for (Criterion criterion : crits) {
                        if (criterion != null) {
                            crit.add(criterion);
                            countCrit.add(criterion);
                        }
                    }
                    crit.addOrder(order);

                    List<T> data = (List<T>) crit.list();//

                    List rowCountList = countCrit.setProjection(Projections.rowCount()).list();

                    int numberObjects = 0;
                    if (rowCountList.size() > 0) {
                        numberObjects = Integer.parseInt(rowCountList.get(0).toString());
                    }
                    return new PageResult<T>(data, numberObjects);
                } catch (Exception ex) {
                    ex.printStackTrace();
                    return new MonitorDaoException("查询分页记录时发生异常：" + ex.getMessage());
                }
            }
        });
        if (result instanceof MonitorDaoException) {
            throw (MonitorDaoException) result;
        } else {
            return (PageResult<T>) result;
        }
    }


    /**
     * <pre>
     * 	根据条件查询出分页的内容
     * </pre>
     *
     * @param condition
     * @return
     */
    public int importBySqlCount(final String condition) throws MonitorDaoException {
        final List<int[]> flowInfoAll = new ArrayList<int[]>();
        doWork(new Work() {
            public void execute(Connection conn) {
                Statement stat = null;
                String[] sqlHql = condition.split(";");
                try {
                    stat = conn.createStatement();
                    for (String hql : sqlHql) {
                        stat.addBatch(hql);
                    }
                    flowInfoAll.add(stat.executeBatch());

                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    if (stat != null) {
                        try {
                            stat.close();
                            conn.close();
                        } catch (Exception ex) {
                        }
                    }
                }
            }
        });
        return flowInfoAll.get(0).length;
    }
}
